package com.sky.loveshop.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.json.JSONUtil;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.sky.loveshop.entity.*;
import com.sky.loveshop.entity.exception.BizException;
import com.sky.loveshop.entity.exception.BizExceptionEnum;
import com.sky.loveshop.entity.qo.PrivateOrderRequest;
import com.sky.loveshop.entity.qo.SkuQO;
import com.sky.loveshop.entity.qo.StockParam;
import com.sky.loveshop.entity.qo.StockRequest;
import com.sky.loveshop.entity.vo.ProductVO;
import com.sky.loveshop.entity.vo.ShelfVO;
import com.sky.loveshop.entity.vo.SkuVO;
import com.sky.loveshop.mapper.SkuMapper;
import com.sky.loveshop.service.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import tk.mybatis.mapper.entity.Example;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author xcy
 * @version V1.0
 * @description
 * @date 2024/8/18 0:06
 */
@Slf4j
@Service
public class SkuServiceImpl implements SkuService {

    @Autowired
    private SkuMapper skuMapper;
    @Autowired
    private CategoryService categoryService;
    @Autowired
    private ShopService shopService;
    @Autowired
    private ShelfService shelfService;
    @Autowired
    private ProductService productService;
    @Autowired
    private StockChangeHistoryService stockChangeHistoryService;

    @Override
    public List<SkuVO> listSku(SkuQO qo) {
        log.info("listSkuParam = {}", JSONUtil.toJsonStr(qo));
        // 条件查询支持位置码查询 通过位置码和商店id查询skuId
        if (StringUtils.isNotEmpty(qo.getKeyWords())) {
            Shelf shelf = shelfService.getShelfByNameAndShopId(qo.getKeyWords(), qo.getShopId());
            if (shelf == null) {
                return new Page<>();
            }
            Example example = new Example(Sku.class);
            example.createCriteria().andEqualTo("shelfId", shelf.getId());
            Sku sku = skuMapper.selectOneByExample(example);
            qo.setId(sku.getId());
        }
        return skuMapper.searchAll(qo);
    }

    @Override
    public PageInfo<SkuVO> listSkuPages(SkuQO qo) {
        log.info("listSkuPagesParam = {}", JSONUtil.toJsonStr(qo));
        // 条件查询支持位置码查询 通过位置码和商店id查询skuId
        if (StringUtils.isNotEmpty(qo.getKeyWords())) {
            Shelf shelf = shelfService.getShelfByNameAndShopId(qo.getKeyWords(), qo.getShopId());
            if (null == shelf) {
                return new PageInfo<>();
            }
            Example example = new Example(Sku.class);
            example.createCriteria().andEqualTo("shelfId", shelf.getId());
            Sku sku = skuMapper.selectOneByExample(example);
            qo.setId(sku.getId());
        }

        PageHelper.startPage(qo.getPageNum(), qo.getPageSize());
        List<SkuVO> skuList = skuMapper.searchAll(qo);
        if (CollectionUtil.isEmpty(skuList)) {
            return new PageInfo<>();
        }
        List<Integer> shopIds = skuList.stream().map(Sku::getShopId).distinct().collect(Collectors.toList());
        List<Integer> productIds = skuList.stream().map(Sku::getProductId).distinct().collect(Collectors.toList());
        List<Integer> shelfIds = skuList.stream().map(Sku::getShelfId).distinct().collect(Collectors.toList());

        List<Shop> shopList = shopService.getShopsByIds(shopIds);
        Map<Integer, String> shopNameMap = shopList.stream().collect(Collectors.toMap(Shop::getId, Shop::getName));

        List<Product> productList = productService.getProductsByIds(productIds);
        Map<Integer, String> productNameMap = productList.stream().collect(Collectors.toMap(Product::getId, Product::getName));
        Map<Integer, Integer> productId2CategoryIdMap = productList.stream().collect(Collectors.toMap(Product::getId, Product::getCategoryId));
        Map<Integer, String> idBarCodeMap = productList.stream().collect(Collectors.toMap(Product::getId, Product::getBarCode));
        Map<Integer, String> id2PicMap = productList.stream().collect(Collectors.toMap(Product::getId, Product::getPicture));

        List<Integer> categoryIds = productList.stream().map(Product::getCategoryId).distinct().collect(Collectors.toList());
        List<Category> categoryList = categoryService.getCategoryListByIds(categoryIds);
        Map<Integer, String> categoryNameMap = categoryList.stream().collect(Collectors.toMap(Category::getId, Category::getName));

        List<Shelf> shelfList = shelfService.getShelfListByIds(shelfIds);
        Map<Integer, String> shelfNameMap = shelfList.stream().collect(Collectors.toMap(Shelf::getId, Shelf::getName));
        Map<Integer, Shelf> idShelfMap = shelfList.stream().collect(Collectors.toMap(Shelf::getId, Function.identity()));

        skuList.stream().forEach(s -> {
            s.setProductName(productNameMap.get(s.getProductId()));
            s.setPicture(id2PicMap.get(s.getProductId()));
            s.setShopName(shopNameMap.get(s.getShopId()));
            s.setShelfName(shelfNameMap.get(s.getShelfId()));
            s.setCategoryId(productId2CategoryIdMap.get(s.getProductId()));
            s.setBarCode(idBarCodeMap.get(s.getProductId()));
            s.setCategoryName(categoryNameMap.get(productId2CategoryIdMap.get(s.getProductId())));
            String area = idShelfMap.get(s.getShelfId()).getArea();
            Integer level = idShelfMap.get(s.getShelfId()).getLevel();
            Integer no = idShelfMap.get(s.getShelfId()).getNo();
            s.setArea(area);
            s.setLevel(level);
            s.setNo(no);
            Integer dangerFlag = (s.getDangerNumber() >= s.getStockNumber()) ? 1 : 0;
            s.setDangerFlag(dangerFlag);
            s.setPlace(area + level + String.format("%02d", no));
        });
        return new PageInfo<>(skuList);
    }

    @Override
    public SkuVO getSkuById(Integer id) throws BizException {
        Sku sku = skuMapper.getSkuById(id);
        if (null == sku) {
            throw new BizException(BizExceptionEnum.SKU_NOT_EXIST);
        }
        SkuVO skuVO = new SkuVO();
        ProductVO product = productService.getProductById(sku.getProductId());
        ShelfVO shelf = shelfService.getShelfById(sku.getShelfId());
        Shop shop = shopService.getShopById(sku.getShopId());
        Category category = categoryService.getCategoryById(product.getCategoryId());
        BeanUtils.copyProperties(sku, skuVO);
        skuVO.setCategoryId(product.getCategoryId());
        skuVO.setShopName(shop.getName());
        skuVO.setProductName(product.getName());
        skuVO.setBarCode(product.getBarCode());
        skuVO.setUpc(product.getUpcCode());
        skuVO.setShelfName(shelf.getName());
        skuVO.setCategoryName(category.getName());
        skuVO.setArea(shelf.getArea());
        skuVO.setLevel(shelf.getLevel());
        skuVO.setNo(shelf.getNo());
        skuVO.setPlace(shelf.getArea() + shelf.getLevel() + String.format("%02d", shelf.getNo()));
        return skuVO;
    }

    @Override
    public SkuVO getSkuByProductAndShopId(Integer productId, Integer shopId) {
        Example example = new Example(Sku.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("productId", productId);
        criteria.andEqualTo("shopId", shopId);
        Sku sku = skuMapper.selectOneByExample(example);
        SkuVO skuVO = new SkuVO();
        ProductVO product = productService.getProductById(sku.getProductId());
        ShelfVO shelf = shelfService.getShelfById(sku.getShelfId());
        Shop shop = shopService.getShopById(sku.getShopId());
        Category category = categoryService.getCategoryById(product.getCategoryId());
        BeanUtils.copyProperties(sku, skuVO);
        skuVO.setCategoryId(product.getCategoryId());
        skuVO.setShopName(shop.getName());
        skuVO.setProductName(product.getName());
        skuVO.setBarCode(product.getBarCode());
        skuVO.setShelfName(shelf.getName());
        skuVO.setCategoryName(category.getName());
        skuVO.setArea(shelf.getArea());
        skuVO.setLevel(shelf.getLevel());
        skuVO.setNo(shelf.getNo());
        skuVO.setPlace(shelf.getArea() + shelf.getLevel() + String.format("%02d", shelf.getNo()));
        return skuVO;
    }

    @Override
    public SkuVO getShelfIdByProductIdAndShopId(Integer productId, Integer shopId) {
        Example example = new Example(Sku.class);
        example.createCriteria().andEqualTo("productId", productId)
                .andEqualTo("shopId", shopId);
        Sku sku = skuMapper.selectOneByExample(example);
        SkuVO skuVO = new SkuVO();
        BeanUtils.copyProperties(sku, skuVO);
        return skuVO;
    }

    @Override
    public List<SkuVO> getSkuListByIds(List<Integer> ids) {

        List<Sku> skuList = skuMapper.getSkuListByIds(ids);

        ArrayList<SkuVO> skuVOList = new ArrayList<>();
        List<Integer> shopIds = skuList.stream().map(Sku::getShopId).distinct().collect(Collectors.toList());
        List<Integer> productIds = skuList.stream().map(Sku::getProductId).distinct().collect(Collectors.toList());
        List<Integer> shelfIds = skuList.stream().map(Sku::getShelfId).distinct().collect(Collectors.toList());

        List<Shop> shopList = shopService.getShopsByIds(shopIds);
        Map<Integer, String> shopNameMap = shopList.stream().collect(Collectors.toMap(Shop::getId, Shop::getName));

        List<Product> productList = productService.getProductsByIds(productIds);
        Map<Integer, String> productNameMap = productList.stream().collect(Collectors.toMap(Product::getId, Product::getName));
        Map<Integer, Integer> productId2CategoryIdMap = productList.stream().collect(Collectors.toMap(Product::getId, Product::getCategoryId));
        Map<Integer, String> productId2BarCodeMap = productList.stream().collect(Collectors.toMap(Product::getId, Product::getBarCode));
        Map<Integer, String> productId2UpcCodeMap = productList.stream().collect(Collectors.toMap(Product::getId, Product::getUpcCode));

        List<Integer> categoryIds = productList.stream().map(Product::getCategoryId).distinct().collect(Collectors.toList());
        List<Category> categoryList = categoryService.getCategoryListByIds(categoryIds);
        Map<Integer, String> categoryNameMap = categoryList.stream().collect(Collectors.toMap(Category::getId, Category::getName));

        List<Shelf> shelfList = shelfService.getShelfListByIds(shelfIds);
        Map<Integer, String> shelfNameMap = shelfList.stream().collect(Collectors.toMap(Shelf::getId, Shelf::getName));
        Map<Integer, Shelf> idShelfMap = shelfList.stream().collect(Collectors.toMap(Shelf::getId, Function.identity()));

        skuList.stream().forEach(s -> {
            SkuVO skuVO = new SkuVO();
            BeanUtils.copyProperties(s, skuVO);
            skuVO.setProductName(productNameMap.get(s.getProductId()));
            skuVO.setShopName(shopNameMap.get(s.getShopId()));
            skuVO.setShelfName(shelfNameMap.get(s.getShelfId()));
            skuVO.setCategoryId(productId2CategoryIdMap.get(s.getProductId()));
            skuVO.setCategoryName(categoryNameMap.get(productId2CategoryIdMap.get(s.getProductId())));
            String area = idShelfMap.get(s.getShelfId()).getArea();
            Integer level = idShelfMap.get(s.getShelfId()).getLevel();
            Integer no = idShelfMap.get(s.getShelfId()).getNo();
            skuVO.setArea(area);
            skuVO.setLevel(level);
            skuVO.setNo(no);
            skuVO.setBarCode(productId2BarCodeMap.get(s.getProductId()));
            skuVO.setPlace(area + level + String.format("%02d", no));
            skuVO.setUpc(productId2UpcCodeMap.get(s.getProductId()));
            skuVOList.add(skuVO);
        });
        return skuVOList;
    }

    @Override
    public List<SkuVO> getSkuListByShelfIds(List<Integer> ids) throws Exception {
        List<Sku> skuList = skuMapper.getSkuListByShelfIds(ids);
        if (CollectionUtil.isEmpty(skuList)) {
            throw new BizException(BizExceptionEnum.SHOP_AREA_LEVEL_NO_DO_HAVE_SKU);
        }
        ArrayList<SkuVO> skuVOList = new ArrayList<>();
        List<Integer> shopIds = skuList.stream().map(Sku::getShopId).distinct().collect(Collectors.toList());
        List<Integer> productIds = skuList.stream().map(Sku::getProductId).distinct().collect(Collectors.toList());
        List<Integer> shelfIds = skuList.stream().map(Sku::getShelfId).distinct().collect(Collectors.toList());

        List<Shop> shopList = shopService.getShopsByIds(shopIds);
        Map<Integer, String> shopNameMap = shopList.stream().collect(Collectors.toMap(Shop::getId, Shop::getName));

        List<Product> productList = productService.getProductsByIds(productIds);
        Map<Integer, Product> id2ProductMap = productList.stream().collect(Collectors.toMap(Product::getId, Function.identity()));

        List<Integer> categoryIds = productList.stream().map(Product::getCategoryId).distinct().collect(Collectors.toList());
        List<Category> categoryList = categoryService.getCategoryListByIds(categoryIds);
        Map<Integer, String> categoryNameMap = categoryList.stream().collect(Collectors.toMap(Category::getId, Category::getName));

        List<Shelf> shelfList = shelfService.getShelfListByIds(shelfIds);
        Map<Integer, String> shelfNameMap = shelfList.stream().collect(Collectors.toMap(Shelf::getId, Shelf::getName));
        Map<Integer, Shelf> idShelfMap = shelfList.stream().collect(Collectors.toMap(Shelf::getId, Function.identity()));

        skuList.stream().forEach(s -> {
            SkuVO skuVO = new SkuVO();
            BeanUtils.copyProperties(s, skuVO);

            Product product = id2ProductMap.get(s.getProductId());
            if (null == product) {
                return;
            }

            skuVO.setShopName(shopNameMap.get(s.getShopId()));
            skuVO.setShelfName(shelfNameMap.get(s.getShelfId()));
            skuVO.setProductName(product.getName());//
            skuVO.setPicture(product.getPicture());
            skuVO.setCategoryId(product.getCategoryId());
            skuVO.setCategoryName(categoryNameMap.get(product.getCategoryId()));
            skuVO.setBarCode(product.getBarCode());
            String area = idShelfMap.get(s.getShelfId()).getArea();
            Integer level = idShelfMap.get(s.getShelfId()).getLevel();
            Integer no = idShelfMap.get(s.getShelfId()).getNo();
            skuVO.setArea(area);
            skuVO.setLevel(level);
            skuVO.setNo(no);
            skuVO.setPlace(area + level + String.format("%02d", no));
            skuVOList.add(skuVO);
        });
        return skuVOList;
    }

    @Override
    public Integer addSku(Sku sku) {
        sku.setStatus(1);
        return skuMapper.insertOne(sku);
    }

    @Override
    public Integer delSkuById(Integer id) {
        return skuMapper.delSkuById(id);
    }

    @Override
    public Integer updateSkuById(Sku sku) {
        return skuMapper.updateSkuById(sku);
    }

    @Override
    @Transactional
    public Integer changeStockNum(StockParam stockParam) {
        skuMapper.changeStockNum(stockParam);
        // 增加库存变更操作记录
        if (stockParam.getUserId() != null) {
            Integer skuId = stockParam.getSkuId();
            Sku sku = skuMapper.getSkuById(skuId);

            StockChangeHistory add = new StockChangeHistory();
            add.setUserId(stockParam.getUserId());
            add.setShopId(sku.getShopId());
            add.setSkuId(skuId);
            add.setChangeType(stockParam.getType());
            add.setChangeNum(stockParam.getNum());
            add.setCreateTime(new Date());
            stockChangeHistoryService.addStockChangeHistory(add);
        }
        return 1;
    }

    @Override
    public PageInfo<SkuVO> getDangerNumberList(StockRequest.Q1 qo) {
        log.info("getDangerNumberListParam = {}", JSONUtil.toJsonStr(qo));
        // 条件查询支持位置码查询 通过位置码和商店id查询skuId
        if (StringUtils.isNotEmpty(qo.getKeyWords())) {
            Shelf shelf = shelfService.getShelfByNameAndShopId(qo.getKeyWords(), qo.getShopId());
            if (shelf == null) {
                return new PageInfo<>();
            }
            qo.setShelfId(shelf.getId());
        }

        PageHelper.startPage(qo.getPageNum(), qo.getPageSize());
        if (qo.getShopId() != null) {
            qo.setShopIds(Arrays.asList(qo.getShopId()));
        }
        List<SkuVO> dangerList = skuMapper.getDangerNumberList(qo);
        dangerList.stream().forEach(sku -> {
            ProductVO product = productService.getProductById(sku.getProductId());
            ShelfVO shelf = shelfService.getShelfById(sku.getShelfId());
            Shop shop = shopService.getShopById(sku.getShopId());
            Category category = categoryService.getCategoryById(product.getCategoryId());
            sku.setCategoryId(product.getCategoryId());
            sku.setShopName(shop.getName());
            sku.setProductName(product.getName());
            sku.setShelfName(shelf.getName());
            sku.setCategoryName(category.getName());
            sku.setArea(shelf.getArea());
            sku.setLevel(shelf.getLevel());
            sku.setNo(shelf.getNo());
            sku.setPlace(shelf.getArea() + shelf.getLevel() + String.format("%02d", shelf.getNo()));
            Integer dangerFlag = (sku.getStockNumber() <= sku.getDangerNumber()) ? 1 : 0;
            sku.setDangerFlag(dangerFlag);
            sku.setPicture(product.getPicture());
            sku.setBarCode(product.getBarCode());
        });
        return new PageInfo<>(dangerList);
    }

    public List<Sku> getSkuListByShoIdAndSkuId(Integer shopId, List<Integer> productIdList) {
        return skuMapper.getSkuListByShoIdAndSkuId(shopId, productIdList);
    }

    @Override
    public List<SkuVO> getSkuVOByShopIdAndName(PrivateOrderRequest.Q1 req) {
        List<Integer> productIdList = productService.getProductIdsByName(req.getProductName());
        List<Sku> skuList = skuMapper.getSkuListByShoIdAndSkuId(req.getShopId(), productIdList);

        ArrayList<SkuVO> skuVOList = new ArrayList<>();
        List<Integer> shopIds = skuList.stream().map(Sku::getShopId).distinct().collect(Collectors.toList());
        List<Integer> productIds = skuList.stream().map(Sku::getProductId).distinct().collect(Collectors.toList());
        //List<Integer> shelfIds = skuList.stream().map(Sku::getShelfId).distinct().collect(Collectors.toList());

        List<Shop> shopList = shopService.getShopsByIds(shopIds);
        Map<Integer, String> shopNameMap = shopList.stream().collect(Collectors.toMap(Shop::getId, Shop::getName));

        List<Product> productList = productService.getProductsByIds(productIds);
        Map<Integer, String> productNameMap = productList.stream().collect(Collectors.toMap(Product::getId, Product::getName));
        Map<Integer, Integer> productId2CategoryIdMap = productList.stream().collect(Collectors.toMap(Product::getId, Product::getCategoryId));
        Map<Integer, String> productId2BarCodeMap = productList.stream().collect(Collectors.toMap(Product::getId, Product::getBarCode));

        List<Integer> categoryIds = productList.stream().map(Product::getCategoryId).distinct().collect(Collectors.toList());
        List<Category> categoryList = categoryService.getCategoryListByIds(categoryIds);
        Map<Integer, String> categoryNameMap = categoryList.stream().collect(Collectors.toMap(Category::getId, Category::getName));

        //List<Shelf> shelfList = shelfService.getShelfListByIds(shelfIds);
        //Map<Integer, String> shelfNameMap = shelfList.stream().collect(Collectors.toMap(Shelf::getId, Shelf::getName));
        //Map<Integer, Shelf> idShelfMap = shelfList.stream().collect(Collectors.toMap(Shelf::getId, Function.identity()));

        skuList.stream().forEach(s -> {
            SkuVO skuVO = new SkuVO();
            BeanUtils.copyProperties(s, skuVO);
            skuVO.setProductName(productNameMap.get(s.getProductId()));
            skuVO.setShopName(shopNameMap.get(s.getShopId()));
            //skuVO.setShelfName(shelfNameMap.get(s.getShelfId()));
            skuVO.setCategoryId(productId2CategoryIdMap.get(s.getProductId()));
            skuVO.setCategoryName(categoryNameMap.get(productId2CategoryIdMap.get(s.getProductId())));
            //String area = idShelfMap.get(s.getShelfId()).getArea();
            //Integer level = idShelfMap.get(s.getShelfId()).getLevel();
            //Integer no = idShelfMap.get(s.getShelfId()).getNo();
            //skuVO.setArea(area);
            //skuVO.setLevel(level);
            //skuVO.setNo(no);
            skuVO.setBarCode(productId2BarCodeMap.get(s.getProductId()));
            //skuVO.setPlace(area + level + String.format("%02d", no));
            skuVOList.add(skuVO);
        });
        return skuVOList;
    }
}
